package com.ibm.risk.irmp.base.auth.service.impl;


import com.ibm.risk.irmp.base.auth.dao.BizBranchRepository;
import com.ibm.risk.irmp.base.auth.dao.SystemBizBranchRoleRepository;
import com.ibm.risk.irmp.base.auth.dao.SystemUserRepository;
import com.ibm.risk.irmp.base.auth.entity.*;
import com.ibm.risk.irmp.base.auth.service.IOrganizationService;
import com.ibm.risk.irmp.base.auth.vo.OrganizationVo;
import com.ibm.risk.irmp.base.dict.vo.BizBranchParamVo;
import com.ibm.risk.irmp.common.auth.vo.OrgInfoTree;
import com.ibm.risk.irmp.common.auth.vo.OrgInfoVo;
import com.ibm.risk.irmp.common.utils.DaoUtils;
import com.ibm.risk.irmp.common.vo.PagedResult;
import jakarta.persistence.EntityManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
@Transactional(readOnly = true)
@CacheConfig(cacheNames = "IrmpLoginDataCache")
public class OrganizationServiceImpl implements IOrganizationService {
    private static final Logger log = LoggerFactory.getLogger(OrganizationServiceImpl.class);

    @Autowired
    DaoUtils daoUtils;

    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    NamedParameterJdbcTemplate npJdbcTemplate;
    @Autowired
    EntityManager entityManager;
    @Autowired
    SystemUserRepository userRepository;
    @Autowired
    SystemBizBranchRoleRepository systemBizBranchRoleRepository;

    @Autowired
    BizBranchRepository bizBranchRepository;

    @Override
    @Cacheable(key = "methodName + args")
    public PagedResult<SystemUserBase> getBizBranchUserList(String bizBranchCode, String username, Integer pageIndex, Integer pageSize) {
        if (username != null) {
            username = "%" + username + "%";
        } else {
            username = "%%";
        }
        Page<SystemUser> userPage = userRepository.findByBizBranch(bizBranchCode, username, PageRequest.of(pageIndex, pageSize));
        List<SystemUserBase> users = toSystemUserBases(userPage.getContent());
        PagedResult<SystemUserBase> resultList =
                new PagedResult<>((int) userPage.getTotalElements(), users);
        return resultList;
    }
    public List<OrgInfoVo> getOrgListByParentId(String parentId) {
        List<SystemBizBranch> branches;
        if (StringUtils.isEmpty(parentId)) {
            branches = bizBranchRepository.findActiveHeadOrgs();
        } else {
            branches = bizBranchRepository.findByParentCode(parentId, Boolean.TRUE);
        }
        BeanCopier copier = BeanCopier.create(SystemBizBranch.class, OrgInfoVo.class, false);
        return branches.stream().map(b -> {
            OrgInfoVo orgInfoVo = new OrgInfoVo();
            copier.copy(b, orgInfoVo, null);
            return orgInfoVo;
        }).toList();
    }

    @Override
    @Transactional(readOnly = false)
    public void saveBizBranchRoles(String branchCode, List<String> roles) {
        systemBizBranchRoleRepository.deleteAllByBranchCode(branchCode);
        List<SystemBizBranchRole> list = new ArrayList<>();
        if (roles.size() > 0 ) {
            roles.forEach(roleCode->{
                SystemBizBranchRole systemBizBranchRole = new SystemBizBranchRole();
                systemBizBranchRole.setBranchCode(branchCode);
                systemBizBranchRole.setRoleCode(roleCode);
                list.add(systemBizBranchRole);
            });
            systemBizBranchRoleRepository.saveAll(list);
        }
    }

    @Override
    public List<String> getBizBranchRoles(String branchCode) {
        SystemBizBranchRole systemBizBranchRole = new SystemBizBranchRole();
        systemBizBranchRole.setBranchCode(branchCode);
        List<SystemBizBranchRole> list = systemBizBranchRoleRepository.findAll(Example.of(systemBizBranchRole));
        List<String> res = new ArrayList<>();
        list.forEach(i->{
            res.add(i.getRoleCode());
        });
        return res;
    }

    @Override
    public PagedResult<SystemUser> findBizBranchUserList(String bizBranchCode, String userName, Integer pageIndex, Integer pageSize) {
        return null;
    }

    @Override
    public PagedResult<OrgInfoVo> findBizBranchList(BizBranchParamVo param) {
        String branchCode = "";
        String bizBranchName = "";
        if (StringUtils.isNotBlank(param.getBizBranchCode())) {
            branchCode = param.getBizBranchCode();
        }
        if (StringUtils.isNotBlank(param.getBizBranchName())) {
            bizBranchName = param.getBizBranchName();
        }
        BeanCopier copier = BeanCopier.create(SystemBizBranch.class, OrgInfoVo.class, false);
        SystemBizBranch branch = null;
        if (StringUtils.isNotEmpty(branchCode)) {
            branch = bizBranchRepository.findById(branchCode).get();
        }
        Page<SystemBizBranch> branches = bizBranchRepository.findByBranchNameContainingIgnoreCase(bizBranchName, PageRequest.of(param.getPageIndex(), param.getPageSize()));
        List<OrgInfoVo> list = branches.map(b -> {
            OrgInfoVo vo = new OrgInfoVo();
            copier.copy(b, vo, null);
            return vo;
        }).toList();
        if (branch != null) {
            ArrayList<OrgInfoVo> listp = new ArrayList<>(list.size() + 1);
            OrgInfoVo vo = new OrgInfoVo();
            copier.copy(branch, vo, null);
            listp.add(vo);
            listp.addAll(list);
            list = listp;
        }
        return new PagedResult<>((int) branches.getTotalElements(), list);
    }
    private BeanCopier userCopier = BeanCopier.create(SystemUser.class, SystemUserBase.class, false);
    @Override
    @Cacheable(key = "methodName + args")
    public PagedResult<SystemUserBase> getMngBranchUserList(String mngBranchCode, Integer pageIndex, Integer pageSize) {
        Page<SystemUser> userPage = userRepository.findByMngBranch(mngBranchCode, PageRequest.of(pageIndex, pageSize));
        List<SystemUserBase> users = toSystemUserBases(userPage.getContent());
        PagedResult<SystemUserBase> resultList =
                new PagedResult<>((int) userPage.getTotalElements(), users);
        return resultList;
    }

    private List<SystemUserBase> toSystemUserBases(List<? extends SystemUserBase> userPage) {
        List<SystemUserBase> users = userPage.stream().map(u -> {
            SystemUserBase systemUserBase = new SystemUserBase();
            userCopier.copy(u, systemUserBase, null);
            return systemUserBase;
        }).toList();
        return users;
    }

    /**
     * 账务机构(仅读取一级机构)
     */
    @Override
    @Cacheable(key = "methodName + args")
    public List<OrgInfoTree> getLevel1BizBranch(String consFlag) {
//        List<? extends OrganizationVo> fin0 = userRepository.findBranchByConsFlag(consFlag, 0);
//        List<OrgInfoTree> orgInfoTree = toOrgInfoTreeNodes(fin0);
//        log.debug("{} branches found.", fin0.size());
//        List<? extends OrganizationVo> fin1 = userRepository.findBranchByConsFlag(consFlag, 1);
//        orgInfoTree.get(0).setChildren(toOrgInfoTreeNodes(fin1));
//        return orgInfoTree;
        return new ArrayList<>();
    }

    /**
     * 管理机构(仅读取一级机构)
     */
    @Override
    @Cacheable(key = "methodName + args")
    public List<OrgInfoTree> getLevel1MngBranch(String consFlag) {

        List<SystemMngBranch> mngBranch0 = userRepository.findMngBranchByConsFlag(consFlag, 0);
        log.debug("{} branches found.", mngBranch0.size());
        if (mngBranch0.size() == 0) {
            return Collections.EMPTY_LIST;
        }
        ArrayList<OrgInfoTree> mngTree = toOrgInfoTreeNodes(mngBranch0);
        List<SystemMngBranch> mngBranch1 = userRepository.findMngBranchByConsFlag(consFlag, 1);
        ArrayList<OrgInfoTree> orgNodel1 = toOrgInfoTreeNodes(mngBranch1);
        mngTree.get(0).setChildren(orgNodel1);
        return mngTree;
    }

    @Override
    public List<? extends OrgInfoTree> getBizOrgTree() {
        List<SystemBizBranch> headOrgs = bizBranchRepository.findActiveHeadOrgs();
        List<OrgInfoTree> orgNodes = toOrgInfoTreeNodes(headOrgs);
        return orgNodes;
    }



    private static ArrayList<OrgInfoTree> toOrgInfoTreeNodes(List<? extends OrganizationVo> mngBranch1) {
        ArrayList<OrgInfoTree> orgNodes = new ArrayList<>(mngBranch1.size());
        for (OrganizationVo branch : mngBranch1) {
            OrgInfoTree orgNode = new OrgInfoTree();
            orgNode.setBranchCode(branch.getBranchCode());
            orgNode.setBranchName(branch.getBranchName());
            orgNode.setBelongLevel(branch.getBelongLevel());
            orgNodes.add(orgNode);
            if (!branch.getChildren().isEmpty()) {
                orgNode.setChildren(toOrgInfoTreeNodes(branch.getChildren()));
            }
        }
        return orgNodes;
    }

//    @Cacheable(key = "methodName + args")
//    public List<OrgInfoVo> getTopFinOrgs(String username) {
//        Stream<? extends OrgInfoVo> stream = getUserFinOrgData(username).stream();
//        return (List<OrgInfoVo>) stream  //.filter(x -> ((String)x.get("CONS_FLAG")).startsWith("F"))
//                .filter(x -> x.getBelongLevel() == 0 || x.getBelongLevel() == 1).toList();
//
//    }


//    /**
//     * 获取切换报告期/分支机构页面的分支机构
//     *
//     * @return
//     */
//    @Override
//    @Cacheable(key = "methodName + args")
//    public List<OrgInfoVo> getTopMngOrgs(String username) {
//        List<Map<String, String>> resultList = new ArrayList<>();
//        List<OrgInfoVo> userMngOrgData = (List<OrgInfoVo>) getUserMngOrgs(username);
//        return userMngOrgData.stream()  //.filter(x -> ((String)x.get("CONS_FLAG")).startsWith("F"))
//                .filter(x -> x.getBelongLevel() == 0 || x.getBelongLevel() == 1).toList();
//
//    }

//    /**
//     * 读取用户账务机构组
//     */
//    @Cacheable(key = "methodName + args")
//    public List<OrgInfoVo> getUserOrgs(Long userId) {
////        String sqlOrg = "select distinct p.FIN_BRANCH_CODE  AS GROUP_CODE, p.FIN_BRANCH_NAME  AS GROUP_NAME \n" +
////                " from RI_BASE_AUTH_FIN_BRANCH p\n" +
////                " inner join RI_BASE_AUTH_ORG_USER ou on p.FIN_BRANCH_CODE = ou.FIN_BRANCH_CODE\n" +
////                " where ou.user_id = :userId\n" +
////                " order by p.FIN_BRANCH_CODE";
//        List<? extends OrgInfoVo> userFinBranchList = userRepository.getUserFinBranchList(userId);
//        return (List<OrgInfoVo>) userFinBranchList;
//    }

//    /**
//     * 读取用户管理机构组
//     */
//    @Cacheable(key = "methodName + args")
//    public List<OrgInfoVo> getUserMngOrgs(Long userId) {
////        String sqlOrg = "select distinct p.MNG_BRANCH_CODE  AS MNG_GROUP_CODE, p.MNG_BRANCH_NAME  AS MNG_GROUP_NAME \n" +
////                " from RI_BASE_AUTH_MNG_BRANCH p\n" +
////                " inner join RI_BASE_AUTH_MNG_ORG_USER ou on p.MNG_BRANCH_CODE = ou.MNG_BRANCH_CODE\n" +
////                " where ou.user_id = :userId\n" +
////                " order by p.MNG_BRANCH_CODE";
////        NativeQuery queryOrg = (NativeQuery) entityManager.createNativeQuery(sqlOrg);
////
////        List<Map<String, Object>> orgs = queryOrg.setParameter("userId", userId)
////                .setResultTransformer(BeanListUtils.upperMapTransformer)
////                .getResultList();
//        List<? extends OrgInfoVo> userMngBranchList = userRepository.getAllUserMngBranchList(userId);
//        return (List<OrgInfoVo>) userMngBranchList;//.stream().map(b -> new OrgInfoVo((String) b.get("branch_code"), (String) b.get("branch_name"), (Integer) b.get("belong_level"))).toList();
//    }
//
//    /**
//     * 读取用户授权访问数据的组织机构
//     */
//    @Cacheable(key = "methodName + args")
//    public List<OrgInfoVo> getUserFinOrgData(String username) {
////        String sqlOrgData =
////                "select distinct * from (SELECT p.BRANCH_CODE, p.BRANCH_NAME, p.BELONG_LEVEL FROM RI_BASE_AUTH_FIN_BRANCH p\n" +
////                        "  INNER JOIN RI_BASE_AUTH_ORG_USER ou ON ou.BRANCH_CODE = p.BRANCH_CODE \n" +
////                        "  WHERE ou.user_id = :userId\n" +
////                        "  UNION \n" +
////                        "  SELECT p.BRANCH_CODE, p.BRANCH_NAME, p.BELONG_LEVEL FROM RI_BASE_AUTH_FIN_BRANCH p\n" +
////                        "  INNER JOIN RI_BASE_AUTH_ORG_USER ou ON ou.BRANCH_CODE = p.L1_BRANCH_CODE \n" +
////                        "  WHERE ou.user_id = :userId\n" +
////                        ") as atab ORDER BY BELONG_LEVEL, BRANCH_CODE";
////        return getMaps(userId, sqlOrgData);
//        List<? extends OrgInfoVo> userBranchList = userRepository.findByUserName(username);
//        return (List<OrgInfoVo>) userBranchList;
//        //userBranchList.stream().map(b -> new OrgInfoVo((String) b.get("branch_code"), (String) b.get("branch_name"), (Integer) b.get("belong_level"))).toList();
//
//    }

//    /**
//     * 读取用户授权访问数据的组织机构
//     */
//    @Override
//    @Cacheable(key = "methodName + args")
//    public List<OrgInfoVo> getUserMngOrgData(Long userId) {
////        List<SystemMngBranch> userMngBranchList = userRepository.getUserMngBranchList(userId);
////        String sqlMngOrgData =
////                "select distinct * from (SELECT p.BRANCH_CODE, p.BRANCH_NAME, p.BELONG_LEVEL FROM RI_BASE_AUTH_MNG_BRANCH p\n" +
////                        "  INNER JOIN RI_BASE_AUTH_MNG_ORG_USER ou ON ou.BRANCH_CODE = p.BRANCH_CODE \n" +
////                        "  WHERE ou.user_id = :userId\n" +
////                        "  UNION \n" +
////                        "  SELECT p.BRANCH_CODE, p.BRANCH_NAME, p.BELONG_LEVEL FROM RI_BASE_AUTH_MNG_BRANCH p\n" +
////                        "  INNER JOIN RI_BASE_AUTH_MNG_ORG_USER ou ON ou.BRANCH_CODE = p.L1_BRANCH_CODE \n" +
////                        "  WHERE ou.user_id = :userId\n" +
////                        ") as atab ORDER BY BELONG_LEVEL, BRANCH_CODE";
////        return getMaps(userId, sqlMngOrgData);
//        List<? extends OrgInfoVo> userMngBranchList = userRepository.getAllUserMngBranchList(userId);
//        return (List<OrgInfoVo>) userMngBranchList;
//    }

//    private List<Map<String, Object>> getMaps(Long userId, String sqlRole) {
//
//        List<Map<String, Object>> maps = //BeanListUtils.toMaps(lines, props);
//                npJdbcTemplate.queryForList(sqlRole, Map.of("userId", userId));
//        return maps;
//    }
}
